home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of California at Berkeley. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-
- #ifndef lint
- static char sccsid[] = "@(#)readmsg.c 2.10 (Berkeley) 12/23/87";
- #endif /* not lint */
-
- #include "globals.h"
- #include <protocols/timed.h>
-
- extern char *tsptype[];
-
- /*
- * LOOKAT checks if the message is of the requested type and comes from
- * the right machine, returning 1 in case of affirmative answer
- */
-
- #define LOOKAT(msg, mtype, mfrom, netp, froms) \
- (((((mtype) == TSP_ANY) || ((mtype) == (msg).tsp_type)) && \
- (((mfrom) == NULL) || (strcmp((mfrom), (msg).tsp_name) == 0)) && \
- (((netp) == NULL) || \
- (((netp)->mask & (froms).sin_addr.s_addr) == (netp)->net))) \
- ? 1 : 0)
-
- #define MORETIME(rtime, rtout) \
- (((rtime).tv_sec > (rtout).tv_sec || \
- ((rtime).tv_sec == (rtout).tv_sec && \
- (rtime).tv_usec >= (rtout).tv_usec)) \
- ? 0 : 1)
-
- struct timeval rtime, rwait, rtout;
- struct tsp msgin;
- static struct tsplist {
- struct tsp info;
- struct sockaddr_in addr;
- struct tsplist *p;
- } msgslist;
- struct sockaddr_in from;
- struct netinfo *fromnet;
-
- /*
- * `readmsg' returns message `type' sent by `machfrom' if it finds it
- * either in the receive queue, or in a linked list of previously received
- * messages that it maintains.
- * Otherwise it waits to see if the appropriate message arrives within
- * `intvl' seconds. If not, it returns NULL.
- */
-
- struct tsp *
- readmsg(type, machfrom, intvl, netfrom)
-
- int type;
- char *machfrom;
- struct timeval *intvl;
- struct netinfo *netfrom;
- {
- int length;
- fd_set ready;
- static struct tsplist *head = &msgslist;
- static struct tsplist *tail = &msgslist;
- struct tsplist *prev;
- register struct netinfo *ntp;
- register struct tsplist *ptr;
-
- if (trace) {
- fprintf(fd, "looking for %s from %s\n",
- tsptype[type], machfrom == NULL ? "ANY" : machfrom);
- ptr = head->p;
- fprintf(fd, "msgqueue:\n");
- while (ptr != NULL) {
- fprintf(fd, "\t");
- print(&ptr->info, &ptr->addr);
- ptr = ptr->p;
- }
- }
-
- ptr = head->p;
- prev = head;
-
- /*
- * Look for the requested message scanning through the
- * linked list. If found, return it and free the space
- */
-
- while (ptr != NULL) {
- if (LOOKAT(ptr->info, type, machfrom, netfrom, ptr->addr)) {
- msgin = ptr->info;
- from = ptr->addr;
- prev->p = ptr->p;
- if (ptr == tail)
- tail = prev;
- free((char *)ptr);
- fromnet = NULL;
- if (netfrom == NULL)
- for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
- if ((ntp->mask & from.sin_addr.s_addr) ==
- ntp->net) {
- fromnet = ntp;
- break;
- }
- }
- else
- fromnet = netfrom;
- if (trace) {
- fprintf(fd, "readmsg: ");
- print(&msgin, &from);
- }
- return(&msgin);
- } else {
- prev = ptr;
- ptr = ptr->p;
- }
- }
-
- /*
- * If the message was not in the linked list, it may still be
- * coming from the network. Set the timer and wait
- * on a select to read the next incoming message: if it is the
- * right one, return it, otherwise insert it in the linked list.
- */
-
- (void)gettimeofday(&rtime, (struct timezone *)0);
- rtout.tv_sec = rtime.tv_sec + intvl->tv_sec;
- rtout.tv_usec = rtime.tv_usec + intvl->tv_usec;
- if (rtout.tv_usec > 1000000) {
- rtout.tv_usec -= 1000000;
- rtout.tv_sec++;
- }
-
- FD_ZERO(&ready);
- for (; MORETIME(rtime, rtout);
- (void)gettimeofday(&rtime, (struct timezone *)0)) {
- rwait.tv_sec = rtout.tv_sec - rtime.tv_sec;
- rwait.tv_usec = rtout.tv_usec - rtime.tv_usec;
- if (rwait.tv_usec < 0) {
- rwait.tv_usec += 1000000;
- rwait.tv_sec--;
- }
- if (rwait.tv_sec < 0)
- rwait.tv_sec = rwait.tv_usec = 0;
-
- if (trace) {
- fprintf(fd, "readmsg: wait: (%d %d)\n",
- rwait.tv_sec, rwait.tv_usec);
- }
- FD_SET(sock, &ready);
- if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0,
- &rwait)) {
- length = sizeof(struct sockaddr_in);
- if (recvfrom(sock, (char *)&msgin, sizeof(struct tsp),
- 0, &from, &length) < 0) {
- syslog(LOG_ERR, "receiving datagram packet: %m");
- exit(1);
- }
-
- bytehostorder(&msgin);
-
- if (msgin.tsp_vers > TSPVERSION) {
- if (trace) {
- fprintf(fd, "readmsg: version mismatch\n");
- /* should do a dump of the packet, but... */
- }
- continue;
- }
-
- fromnet = NULL;
- for (ntp = nettab; ntp != NULL; ntp = ntp->next)
- if ((ntp->mask & from.sin_addr.s_addr) ==
- ntp->net) {
- fromnet = ntp;
- break;
- }
-
- /*
- * drop packets from nets we are ignoring permanently
- */
- if (fromnet == NULL) {
- /*
- * The following messages may originate on
- * this host with an ignored network address
- */
- if (msgin.tsp_type != TSP_TRACEON &&
- msgin.tsp_type != TSP_SETDATE &&
- msgin.tsp_type != TSP_MSITE &&
- #ifdef TESTING
- msgin.tsp_type != TSP_TEST &&
- #endif
- msgin.tsp_type != TSP_TRACEOFF) {
- if (trace) {
- fprintf(fd, "readmsg: discarded: ");
- print(&msgin, &from);
- }
- continue;
- }
- }
-
- /*
- * Throw away messages coming from this machine, unless
- * they are of some particular type.
- * This gets rid of broadcast messages and reduces
- * master processing time.
- */
- if ( !(strcmp(msgin.tsp_name, hostname) != 0 ||
- msgin.tsp_type == TSP_SETDATE ||
- #ifdef TESTING
- msgin.tsp_type == TSP_TEST ||
- #endif
- msgin.tsp_type == TSP_MSITE ||
- (msgin.tsp_type == TSP_LOOP &&
- msgin.tsp_hopcnt != 10) ||
- msgin.tsp_type == TSP_TRACEON ||
- msgin.tsp_type == TSP_TRACEOFF)) {
- if (trace) {
- fprintf(fd, "readmsg: discarded: ");
- print(&msgin, &from);
- }
- continue;
- }
-
- /*
- * Send acknowledgements here; this is faster and avoids
- * deadlocks that would occur if acks were sent from a
- * higher level routine. Different acknowledgements are
- * necessary, depending on status.
- */
- if (fromnet->status == MASTER)
- masterack();
- else if (fromnet->status == SLAVE)
- slaveack();
- else
- ignoreack();
-
- if (LOOKAT(msgin, type, machfrom, netfrom, from)) {
- if (trace) {
- fprintf(fd, "readmsg: ");
- print(&msgin, &from);
- }
- return(&msgin);
- } else {
- tail->p = (struct tsplist *)
- malloc(sizeof(struct tsplist));
- tail = tail->p;
- tail->p = NULL;
- tail->info = msgin;
- tail->addr = from;
- }
- } else {
- break;
- }
- }
- return((struct tsp *)NULL);
- }
-
- /*
- * `slaveack' sends the necessary acknowledgements:
- * only the type ACK is to be sent by a slave
- */
-
- slaveack()
- {
- int length;
- struct tsp resp;
-
- length = sizeof(struct sockaddr_in);
- switch(msgin.tsp_type) {
-
- case TSP_ADJTIME:
- case TSP_SETTIME:
- case TSP_ACCEPT:
- case TSP_REFUSE:
- case TSP_TRACEON:
- case TSP_TRACEOFF:
- case TSP_QUIT:
- resp = msgin;
- resp.tsp_type = TSP_ACK;
- resp.tsp_vers = TSPVERSION;
- (void)strcpy(resp.tsp_name, hostname);
- if (trace) {
- fprintf(fd, "Slaveack: ");
- print(&resp, &from);
- }
- bytenetorder(&resp); /* this is not really necessary here */
- if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0,
- &from, length) < 0) {
- syslog(LOG_ERR, "sendto: %m");
- exit(1);
- }
- break;
- default:
- break;
- }
- }
-
- /*
- * Certain packets may arrive from this machine on ignored networks.
- * These packets should be acknowledged.
- */
-
- ignoreack()
- {
- int length;
- struct tsp resp;
-
- length = sizeof(struct sockaddr_in);
- switch(msgin.tsp_type) {
-
- case TSP_TRACEON:
- case TSP_TRACEOFF:
- resp = msgin;
- resp.tsp_type = TSP_ACK;
- resp.tsp_vers = TSPVERSION;
- (void)strcpy(resp.tsp_name, hostname);
- if (trace) {
- fprintf(fd, "Ignoreack: ");
- print(&resp, &from);
- }
- bytenetorder(&resp); /* this is not really necessary here */
- if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0,
- &from, length) < 0) {
- syslog(LOG_ERR, "sendto: %m");
- exit(1);
- }
- break;
- default:
- break;
- }
- }
-
- /*
- * `masterack' sends the necessary acknowledgments
- * to the messages received by a master
- */
-
- masterack()
- {
- int length;
- struct tsp resp;
-
- length = sizeof(struct sockaddr_in);
-
- resp = msgin;
- resp.tsp_vers = TSPVERSION;
- (void)strcpy(resp.tsp_name, hostname);
-
- switch(msgin.tsp_type) {
-
- case TSP_QUIT:
- case TSP_TRACEON:
- case TSP_TRACEOFF:
- case TSP_MSITE:
- case TSP_MSITEREQ:
- resp.tsp_type = TSP_ACK;
- bytenetorder(&resp);
- if (trace) {
- fprintf(fd, "Masterack: ");
- print(&resp, &from);
- }
- if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0,
- &from, length) < 0) {
- syslog(LOG_ERR, "sendto: %m");
- exit(1);
- }
- break;
- case TSP_RESOLVE:
- case TSP_MASTERREQ:
- resp.tsp_type = TSP_MASTERACK;
- bytenetorder(&resp);
- if (trace) {
- fprintf(fd, "Masterack: ");
- print(&resp, &from);
- }
- if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0,
- &from, length) < 0) {
- syslog(LOG_ERR, "sendto: %m");
- exit(1);
- }
- break;
- case TSP_SETDATEREQ:
- resp.tsp_type = TSP_DATEACK;
- bytenetorder(&resp);
- if (trace) {
- fprintf(fd, "Masterack: ");
- print(&resp, &from);
- }
- if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0,
- &from, length) < 0) {
- syslog(LOG_ERR, "sendto: %m");
- exit(1);
- }
- break;
- default:
- break;
- }
- }
-
- /*
- * Print a TSP message
- */
- print(msg, addr)
- struct tsp *msg;
- struct sockaddr_in *addr;
- {
- switch (msg->tsp_type) {
-
- case TSP_LOOP:
- fprintf(fd, "%s %d %d (#%d) %s %s\n",
- tsptype[msg->tsp_type],
- msg->tsp_vers,
- msg->tsp_seq,
- msg->tsp_hopcnt,
- msg->tsp_name,
- inet_ntoa(addr->sin_addr));
- break;
-
- case TSP_SETTIME:
- case TSP_ADJTIME:
- case TSP_SETDATE:
- case TSP_SETDATEREQ:
- fprintf(fd, "%s %d %d (%d, %d) %s %s\n",
- tsptype[msg->tsp_type],
- msg->tsp_vers,
- msg->tsp_seq,
- msg->tsp_time.tv_sec,
- msg->tsp_time.tv_usec,
- msg->tsp_name,
- inet_ntoa(addr->sin_addr));
- break;
-
- default:
- fprintf(fd, "%s %d %d %s %s\n",
- tsptype[msg->tsp_type],
- msg->tsp_vers,
- msg->tsp_seq,
- msg->tsp_name,
- inet_ntoa(addr->sin_addr));
- break;
- }
- }
-